home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue42 / alfresco / AALnkLst.pas next >
Encoding:
Pascal/Delphi Source File  |  1999-01-03  |  18.2 KB  |  751 lines

  1. unit AALnkLst;
  2.  
  3. interface
  4.  
  5. uses
  6.   SysUtils;
  7.  
  8. {$IFOPT D+}
  9. {$DEFINE InDebugMode}
  10. {$ENDIF}
  11.  
  12. {$DEFINE UseNodeManager}
  13.  
  14. const
  15.   PageNodeCount = 30;
  16.  
  17. type
  18.   TaaCompareFunction = function (aItem1, aItem2 : pointer) : integer;
  19.  
  20. type
  21.   PsllNode = ^TsllNode;
  22.   TsllNode = packed record
  23.     sllnNext : PsllNode;
  24.     sllnData : pointer;
  25.   end;
  26.  
  27.   TaaSingleList = class
  28.     private
  29.       FCount    : integer;
  30.       FCursor   : PsllNode;
  31.       FHead     : PsllNode;
  32.     protected
  33.     public
  34.       constructor Create;
  35.       destructor Destroy; override;
  36.  
  37.       procedure InsertAfter(aItem : pointer);
  38.       function DeleteAfter : pointer;
  39.  
  40.       function IsBeforeFirst : boolean;
  41.       function IsLast : boolean;
  42.       procedure MoveBeforeFirst;
  43.       function MoveNext : boolean;
  44.  
  45.       procedure Clear;
  46.       function Examine : pointer;
  47.       procedure Sort(aCompare : TaaCompareFunction);
  48.  
  49.       property Count : integer read FCount;
  50.   end;
  51.  
  52. type
  53.   PdllNode = ^TdllNode;
  54.   TdllNode = packed record
  55.     dllnNext : PdllNode;
  56.     dllnPrev : PdllNode;
  57.     dllnData : pointer;
  58.   end;
  59.  
  60.   TaaDoubleList = class
  61.     private
  62.       FCount    : integer;
  63.       FCursor   : PdllNode;
  64.       FHead     : PdllNode;
  65.       FTail     : PdllNode;
  66.     protected
  67.     public
  68.       constructor Create;
  69.       destructor Destroy; override;
  70.  
  71.       procedure InsertBefore(aItem : pointer);
  72.       procedure InsertAfter(aItem : pointer);
  73.       function Delete : pointer;
  74.  
  75.       function IsAfterLast : boolean;
  76.       function IsBeforeFirst : boolean;
  77.       procedure MoveAfterLast;
  78.       procedure MoveBeforeFirst;
  79.       function MoveNext : boolean;
  80.       function MovePrevious : boolean;
  81.  
  82.       procedure Clear;
  83.       function Examine : pointer;
  84.       procedure Sort(aCompare : TaaCompareFunction);
  85.  
  86.       property Count : integer read FCount;
  87.   end;
  88.  
  89.  
  90. type
  91.   TaaStack = class
  92.     private
  93.       FCount : integer;
  94.       FHead  : PsllNode;
  95.     protected
  96.     public
  97.       constructor Create;
  98.       destructor Destroy; override;
  99.  
  100.       procedure Clear;
  101.       function Examine : pointer;
  102.       function IsEmpty : boolean;
  103.       function Pop : pointer;
  104.       procedure Push(aItem : pointer);
  105.  
  106.       property Count : integer read FCount;
  107.   end;
  108.  
  109. type
  110.   TaaQueue = class
  111.     private
  112.       FCount : integer;
  113.       FHead  : PsllNode;
  114.       FTail  : PsllNode;
  115.     protected
  116.     public
  117.       constructor Create;
  118.       destructor Destroy; override;
  119.  
  120.       procedure Clear;
  121.       function Dequeue : pointer;
  122.       procedure Enqueue(aItem : pointer);
  123.       function Examine : pointer;
  124.       function IsEmpty : boolean;
  125.  
  126.       property Count : integer read FCount;
  127.   end;
  128.  
  129.  
  130. implementation
  131.  
  132. {===SingleNodeManager================================================}
  133. type
  134.   PsnmPage = ^TsnmPage;
  135.   TsnmPage = packed record
  136.     snmpNext  : PsnmPage;
  137.     snmpNodes : array [0..pred(PageNodeCount)] of TsllNode;
  138.   end;
  139. {--------}
  140. var
  141.   snmFreeList : PsllNode;
  142.   snmPageList : PsnmPage;
  143. {--------}
  144. procedure snmFreeNode(aNode : PsllNode);
  145. begin
  146.   {$IFDEF UseNodeManager}
  147.   {add the node to the top of the free list}
  148.   aNode^.sllnNext := snmFreeList;
  149.   snmFreeList := aNode;
  150.   {$ELSE}
  151.   Dispose(aNode);
  152.   {$ENDIF}
  153. end;
  154. {--------}
  155. procedure snmAllocPage;
  156. var
  157.   NewPage : PsnmPage;
  158.   i       : integer;
  159. begin
  160.   {get a new page}
  161.   New(NewPage);
  162.   {add it to the current list of pages}
  163.   NewPage^.snmpNext := snmPageList;
  164.   snmPageList := NewPage;
  165.   {add all the nodes on the page to the free list}
  166.   for i := 0 to pred(PageNodeCount) do
  167.     snmFreeNode(@NewPage^.snmpNodes[i]);
  168. end;
  169. {--------}
  170. function snmAllocNode : PsllNode;
  171. begin
  172.   {$IFDEF UseNodeManager}
  173.   {if the free list is empty, allocate a new page of nodes}
  174.   if (snmFreeList = nil) then
  175.     snmAllocPage;
  176.   {return the first node on the free list}
  177.   Result := snmFreeList;
  178.   snmFreeList := Result^.sllnNext;
  179.   {$ELSE}
  180.   New(Result);
  181.   {$ENDIF}
  182.   {$IFDEF InDebugMode}
  183.   Result^.sllnNext := nil;
  184.   Result^.sllnData := nil;
  185.   {$ENDIF}
  186. end;
  187. {====================================================================}
  188.  
  189.  
  190. {===DoubleNodeManager================================================}
  191. type
  192.   PdnmPage = ^TdnmPage;
  193.   TdnmPage = packed record
  194.     dnmpNext  : PdnmPage;
  195.     dnmpNodes : array [0..pred(PageNodeCount)] of TdllNode;
  196.   end;
  197. {--------}
  198. var
  199.   dnmFreeList : PdllNode;
  200.   dnmPageList : PdnmPage;
  201. {--------}
  202. procedure dnmFreeNode(aNode : PdllNode);
  203. begin
  204.   {$IFDEF UseNodeManager}
  205.   {add the node to the top of the free list}
  206.   aNode^.dllnNext := dnmFreeList;
  207.   dnmFreeList := aNode;
  208.   {$ELSE}
  209.   Dispose(aNode);
  210.   {$ENDIF}
  211. end;
  212. {--------}
  213. procedure dnmAllocPage;
  214. var
  215.   NewPage : PdnmPage;
  216.   i       : integer;
  217. begin
  218.   {get a new page}
  219.   New(NewPage);
  220.   {add it to the current list of pages}
  221.   NewPage^.dnmpNext := dnmPageList;
  222.   dnmPageList := NewPage;
  223.   {add all the nodes on the page to the free list}
  224.   for i := 0 to pred(PageNodeCount) do
  225.     dnmFreeNode(@NewPage^.dnmpNodes[i]);
  226. end;
  227. {--------}
  228. function dnmAllocNode : PdllNode;
  229. begin
  230.   {$IFDEF UseNodeManager}
  231.   {if the free list is empty, allocate a new page of nodes}
  232.   if (dnmFreeList = nil) then
  233.     dnmAllocPage;
  234.   {return the first node on the free list}
  235.   Result := dnmFreeList;
  236.   dnmFreeList := Result^.dllnNext;
  237.   {$ELSE}
  238.   New(Result);
  239.   {$ENDIF}
  240.   {$IFDEF InDebugMode}
  241.   Result^.dllnNext := nil;
  242.   Result^.dllnData := nil;
  243.   {$ENDIF}
  244. end;
  245. {====================================================================}
  246.  
  247.  
  248. {===TaaSingleList====================================================}
  249. constructor TaaSingleList.Create;
  250. begin
  251.   inherited Create;
  252.   {allocate a head node}
  253.   FHead := snmAllocNode;
  254.   FHead^.sllnNext := nil;
  255.   FHead^.sllnData := nil;
  256.   {set the cursor to the head node}
  257.   FCursor := FHead;
  258. end;
  259. {--------}
  260. destructor TaaSingleList.Destroy;
  261. begin
  262.   Clear;
  263.   snmFreeNode(FHead);
  264.   inherited Destroy;
  265. end;
  266. {--------}
  267. procedure TaaSingleList.Clear;
  268. var
  269.   Temp : PsllNode;
  270. begin
  271.   Temp := FHead^.sllnNext;
  272.   while (Temp <> nil) do begin
  273.     FHead^.sllnNext := Temp^.sllnNext;
  274.     snmFreeNode(Temp);
  275.     Temp := FHead^.sllnNext;
  276.   end;
  277.   FCount := 0;
  278. end;
  279. {--------}
  280. function TaaSingleList.DeleteAfter : pointer;
  281. var
  282.   OldNode : PsllNode;
  283. begin
  284.   OldNode := FCursor^.sllnNext;
  285.   if (OldNode = nil) then
  286.     raise Exception.Create('TaaSingleList.DeleteAfter: cannot delete - at end of list');
  287.   Result := OldNode^.sllnData;
  288.   FCursor^.sllnNext := OldNode^.sllnNext;
  289.   snmFreeNode(OldNode);
  290.   dec(FCount);
  291. end;
  292. {--------}
  293. function TaaSingleList.Examine : pointer;
  294. begin
  295.   {return the data part of the cursor}
  296.   Result := FCursor^.sllnData;
  297. end;
  298. {--------}
  299. procedure TaaSingleList.InsertAfter(aItem : pointer);
  300. var
  301.   NewNode : PsllNode;
  302. begin
  303.   {allocate a new node and insert after the cursor}
  304.   NewNode := snmAllocNode;
  305.   NewNode^.sllnData := aItem;
  306.   NewNode^.sllnNext := FCursor^.sllnNext;
  307.   FCursor^.sllnNext := NewNode;
  308.   inc(FCount);
  309. end;
  310. {--------}
  311. function TaaSingleList.IsBeforeFirst : boolean;
  312. begin
  313.   Result := FCursor = FHead;
  314. end;
  315. {--------}
  316. function TaaSingleList.IsLast : boolean;
  317. begin
  318.   Result := FCursor^.sllnNext = nil;
  319. end;
  320. {--------}
  321. procedure TaaSingleList.MoveBeforeFirst;
  322. begin
  323.   {set the cursor to the head node}
  324.   FCursor := FHead;
  325. end;
  326. {--------}
  327. function TaaSingleList.MoveNext : boolean;
  328. begin
  329.   {advance the cursor to its own next pointer}
  330.   if (FCursor^.sllnNext = nil) then
  331.     Result := false
  332.   else begin
  333.     FCursor := FCursor^.sllnNext;
  334.     Result := true;
  335.   end;
  336. end;
  337. {--------}
  338. procedure TaaSingleList.Sort(aCompare : TaaCompareFunction);
  339. var
  340.   Walker : PsllNode;
  341.   Temp   : PsllNode;
  342.   WalkerParent : PsllNode;
  343.   TempParent   : PsllNode;
  344. begin
  345.   {if there are zero (or one) items the list is already sorted}
  346.   if (Count <= 1) then
  347.     Exit;
  348.   {perform an insertion sort from the second item onwards}
  349.   WalkerParent := FHead^.sllnNext;
  350.   Walker := WalkerParent^.sllnNext;
  351.   while (Walker <> nil) do begin
  352.     {find where the walker item should be in the sorted list to its
  353.      left - we walk the sorted sublist making a note of the parent as
  354.      we go so that we can insert properly. Note that the loop below
  355.      will terminate in the worst case by the walker node itself - we
  356.      won't run off the end of the list}
  357.     TempParent := FHead;
  358.     Temp := TempParent^.sllnNext;
  359.     while (aCompare(Temp^.sllnData, Walker^.sllnData) < 0) do begin
  360.       TempParent := Temp;
  361.       Temp := TempParent^.sllnNext;
  362.     end;
  363.     {did we find the walker node? If so, it's in the right place so
  364.      move the walker's parent on by one link}
  365.     if (Temp = Walker) then
  366.       WalkerParent := Walker
  367.     {otherwise, move the walker node into the correct place in the
  368.      sorted sublist; leave the walker's parent where it is}
  369.     else begin
  370.       {disconnect the walker node}
  371.       WalkerParent^.sllnNext := Walker^.sllnNext;
  372.       {connect the walker node in the correct place}
  373.       Walker^.sllnNext := Temp;
  374.       TempParent^.sllnNext := Walker;
  375.     end;
  376.     {set the walker node}
  377.     Walker := WalkerParent^.sllnNext;
  378.   end;
  379. end;
  380. {====================================================================}
  381.  
  382.  
  383. {===TaaDoubleList========================================================}
  384. constructor TaaDoubleList.Create;
  385. begin
  386.   inherited Create;
  387.   {allocate a head and a tail node}
  388.   FHead := dnmAllocNode;
  389.   FTail := dnmAllocNode;
  390.   FHead^.dllnNext := FTail;
  391.   FHead^.dllnPrev := nil;
  392.   FHead^.dllnData := nil;
  393.   FTail^.dllnNext := nil;
  394.   FTail^.dllnPrev := FHead;
  395.   FTail^.dllnData := nil;
  396.   {set the cursor to the head node}
  397.   FCursor := FHead;
  398. end;
  399. {--------}
  400. destructor TaaDoubleList.Destroy;
  401. begin
  402.   Clear;
  403.   dnmFreeNode(FHead);
  404.   dnmFreeNode(FTail);
  405.   inherited Destroy;
  406. end;
  407. {--------}
  408. procedure TaaDoubleList.Clear;
  409. var
  410.   Temp : PdllNode;
  411. begin
  412.   Temp := FHead^.dllnNext;
  413.   while (Temp <> FTail) do begin
  414.     FHead^.dllnNext := Temp^.dllnNext;
  415.     dnmFreeNode(Temp);
  416.     Temp := FHead^.dllnNext;
  417.   end;
  418.   FCount := 0;
  419. end;
  420. {--------}
  421. function TaaDoubleList.Delete : pointer;
  422. var
  423.   OldNode : PdllNode;
  424. begin
  425.   OldNode := FCursor;
  426.   if (OldNode = FHead) or (OldNode = FTail) then
  427.     raise Exception.Create('TaaDoubleList.Delete: cannot delete - at start/end of list');
  428.   Result := OldNode^.dllnData;
  429.   OldNode^.dllnPrev^.dllnNext := OldNode^.dllnNext;
  430.   OldNode^.dllnNext^.dllnPrev := OldNode^.dllnPrev;
  431.   FCursor := OldNode^.dllnNext;
  432.   dnmFreeNode(OldNode);
  433.   dec(FCount);
  434. end;
  435. {--------}
  436. function TaaDoubleList.Examine : pointer;
  437. begin
  438.   {return the data part of the cursor}
  439.   Result := FCursor^.dllnData;
  440. end;
  441. {--------}
  442. procedure TaaDoubleList.InsertAfter(aItem : pointer);
  443. var
  444.   NewNode : PdllNode;
  445. begin
  446.   if (FCursor = FTail) then
  447.     FCursor := FCursor^.dllnPrev;
  448.   {allocate a new node and insert after the cursor}
  449.   NewNode := dnmAllocNode;
  450.   NewNode^.dllnData := aItem;
  451.   NewNode^.dllnNext := FCursor^.dllnNext;
  452.   NewNode^.dllnPrev := FCursor;
  453.   FCursor^.dllnNext := NewNode;
  454.   NewNode^.dllnNext^.dllnPrev := NewNode;
  455.   inc(FCount);
  456. end;
  457. {--------}
  458. procedure TaaDoubleList.InsertBefore(aItem : pointer);
  459. var
  460.   NewNode : PdllNode;
  461. begin
  462.   if (FCursor = FHead) then
  463.     FCursor := FCursor^.dllnNext;
  464.   {allocate a new node and insert before the cursor}
  465.   NewNode := dnmAllocNode;
  466.   NewNode^.dllnData := aItem;
  467.   NewNode^.dllnNext := FCursor;
  468.   NewNode^.dllnPrev := FCursor^.dllnPrev;
  469.   NewNode^.dllnPrev^.dllnNext := NewNode;
  470.   FCursor^.dllnPrev := NewNode;
  471.   inc(FCount);
  472. end;
  473. {--------}
  474. function TaaDoubleList.IsAfterLast : boolean;
  475. begin
  476.   Result := FCursor = FTail;
  477. end;
  478. {--------}
  479. function TaaDoubleList.IsBeforeFirst : boolean;
  480. begin
  481.   Result := FCursor = FHead;
  482. end;
  483. {--------}
  484. procedure TaaDoubleList.MoveAfterLast;
  485. begin
  486.   {set the cursor to the tail node}
  487.   FCursor := FTail;
  488. end;
  489. {--------}
  490. procedure TaaDoubleList.MoveBeforeFirst;
  491. begin
  492.   {set the cursor to the head node}
  493.   FCursor := FHead;
  494. end;
  495. {--------}
  496. function TaaDoubleList.MoveNext : boolean;
  497. begin
  498.   {advance the cursor to its own next pointer}
  499.   if (FCursor = FTail) then
  500.     Result := false
  501.   else begin
  502.     FCursor := FCursor^.dllnNext;
  503.     Result := true;
  504.   end;
  505. end;
  506. {--------}
  507. function TaaDoubleList.MovePrevious : boolean;
  508. begin
  509.   {retard the cursor to its own previous pointer}
  510.   if (FCursor = FHead) then
  511.     Result := false
  512.   else begin
  513.     FCursor := FCursor^.dllnPrev;
  514.     Result := true;
  515.   end;
  516. end;
  517. {--------}
  518. procedure TaaDoubleList.Sort(aCompare : TaaCompareFunction);
  519. var
  520.   Walker : PdllNode;
  521.   Temp   : PdllNode;
  522.   WalkerParent : PdllNode;
  523.   TempParent   : PdllNode;
  524. begin
  525.   {if there are zero (or one) items the list is already sorted}
  526.   if (Count <= 1) then
  527.     Exit;
  528.   {perform an insertion sort from the second item onwards}
  529.   WalkerParent := FHead^.dllnNext;
  530.   Walker := WalkerParent^.dllnNext;
  531.   while (Walker <> FTail) do begin
  532.     {find where the walker item should be in the sorted list to its
  533.      left - we walk the sorted sublist making a note of the parent as
  534.      we go so that we can insert properly. Note that the loop below
  535.      will terminate in the worst case by the walker node itself - we
  536.      won't run off the end of the list}
  537.     TempParent := FHead;
  538.     Temp := TempParent^.dllnNext;
  539.     while (aCompare(Temp^.dllnData, Walker^.dllnData) < 0) do begin
  540.       TempParent := Temp;
  541.       Temp := TempParent^.dllnNext;
  542.     end;
  543.     {did we find the walker node? If so, move the walker's parent on
  544.      by one link}
  545.     if (Temp = Walker) then begin
  546.       WalkerParent := Walker;
  547.     end
  548.     {otherwise, move the walker node into the correct place in the
  549.      sorted sublist}
  550.     else begin
  551.       {disconnect the walker node}
  552.       WalkerParent^.dllnNext := Walker^.dllnNext;
  553.       {connect the walker node in the correct place}
  554.       Walker^.dllnNext := Temp;
  555.       TempParent^.dllnNext := Walker;
  556.     end;
  557.     {set the walker node}
  558.     Walker := WalkerParent^.dllnNext;
  559.   end;
  560.   {now patch up all of the previous links}
  561.   WalkerParent := FHead;
  562.   Walker := WalkerParent^.dllnNext;
  563.   while (WalkerParent <> FTail) do begin
  564.     Walker^.dllnPrev := WalkerParent;
  565.     WalkerParent := Walker;
  566.     Walker := WalkerParent^.dllnNext;
  567.   end;
  568. end;
  569. {====================================================================}
  570.  
  571.  
  572. {===TaaStack=========================================================}
  573. constructor TaaStack.Create;
  574. begin
  575.   inherited Create;
  576.   {allocate a head node}
  577.   FHead := snmAllocNode;
  578.   FHead^.sllnNext := nil;
  579.   FHead^.sllnData := nil;
  580. end;
  581. {--------}
  582. destructor TaaStack.Destroy;
  583. begin
  584.   Clear;
  585.   snmFreeNode(FHead);
  586.   inherited Destroy;
  587. end;
  588. {--------}
  589. procedure TaaStack.Clear;
  590. var
  591.   Temp : PsllNode;
  592. begin
  593.   Temp := FHead^.sllnNext;
  594.   while (Temp <> nil) do begin
  595.     FHead^.sllnNext := Temp^.sllnNext;
  596.     snmFreeNode(Temp);
  597.     Temp := FHead^.sllnNext;
  598.   end;
  599.   FCount := 0;
  600. end;
  601. {--------}
  602. function TaaStack.Examine : pointer;
  603. begin
  604.   if (Count = 0) then
  605.     raise Exception.Create('TaaStack.Examine: stack is empty');
  606.   Result := FHead^.sllnNext^.sllnData;
  607. end;
  608. {--------}
  609. function TaaStack.IsEmpty : boolean;
  610. begin
  611.   Result := Count = 0;
  612. end;
  613. {--------}
  614. function TaaStack.Pop : pointer;
  615. var
  616.   Temp : PsllNode;
  617. begin
  618.   if (Count = 0) then
  619.     raise Exception.Create('TaaStack.Pop: stack is empty');
  620.   Temp := FHead^.sllnNext;
  621.   Result := Temp^.sllnData;
  622.   FHead^.sllnNext := Temp^.sllnNext;
  623.   snmFreeNode(Temp);
  624.   dec(FCount);
  625. end;
  626. {--------}
  627. procedure TaaStack.Push(aItem : pointer);
  628. var
  629.   Temp : PsllNode;
  630. begin
  631.   Temp := snmAllocNode;
  632.   Temp^.sllnData := aItem;
  633.   Temp^.sllnNext := FHead^.sllnNext;
  634.   FHead^.sllnNext := Temp;
  635.   inc(FCount);
  636. end;
  637. {====================================================================}
  638.  
  639.  
  640. {===TaaQueue=========================================================}
  641. constructor TaaQueue.Create;
  642. begin
  643.   inherited Create;
  644.   {allocate a head node}
  645.   FHead := snmAllocNode;
  646.   FHead^.sllnNext := nil;
  647.   FHead^.sllnData := nil;
  648.   {make the tail pointer point to the head node}
  649.   FTail := FHead;
  650. end;
  651. {--------}
  652. destructor TaaQueue.Destroy;
  653. begin
  654.   Clear;
  655.   snmFreeNode(FHead);
  656.   inherited Destroy;
  657. end;
  658. {--------}
  659. procedure TaaQueue.Clear;
  660. var
  661.   Temp : PsllNode;
  662. begin
  663.   Temp := FHead^.sllnNext;
  664.   while (Temp <> nil) do begin
  665.     FHead^.sllnNext := Temp^.sllnNext;
  666.     snmFreeNode(Temp);
  667.     Temp := FHead^.sllnNext;
  668.   end;
  669.   FCount := 0;
  670.   {the queue is now empty so make the tail pointer point to the head
  671.    node}
  672.   FTail := FHead;
  673. end;
  674. {--------}
  675. function TaaQueue.Examine : pointer;
  676. begin
  677.   if (Count = 0) then
  678.     raise Exception.Create('TaaQueue.Examine: queue is empty');
  679.   Result := FHead^.sllnNext^.sllnData;
  680. end;
  681. {--------}
  682. function TaaQueue.IsEmpty : boolean;
  683. begin
  684.   Result := Count = 0;
  685. end;
  686. {--------}
  687. function TaaQueue.Dequeue : pointer;
  688. var
  689.   Temp : PsllNode;
  690. begin
  691.   if (Count = 0) then
  692.     raise Exception.Create('TaaQueue.Dequeue: queue is empty');
  693.   Temp := FHead^.sllnNext;
  694.   Result := Temp^.sllnData;
  695.   FHead^.sllnNext := Temp^.sllnNext;
  696.   snmFreeNode(Temp);
  697.   dec(FCount);
  698.   {if we've managed to empty the queue, the tail pointer is now
  699.    invalid, so reset it to point to the head node}
  700.   if (Count = 0) then
  701.     FTail := FHead;
  702. end;
  703. {--------}
  704. procedure TaaQueue.Enqueue(aItem : pointer);
  705. var
  706.   Temp : PsllNode;
  707. begin
  708.   Temp := snmAllocNode;
  709.   Temp^.sllnData := aItem;
  710.   Temp^.sllnNext := nil;
  711.   {add the new node to the tail of the list and make sure the tail
  712.    pointer points to the newly added node}
  713.   FTail^.sllnNext := Temp;
  714.   FTail := Temp;
  715.   inc(FCount);
  716. end;
  717. {====================================================================}
  718.  
  719.  
  720. procedure FinalizeUnit;
  721. var
  722.   STemp : PsnmPage;
  723.   DTemp : PdnmPage;
  724. begin
  725.   {destroy all the single node pages}
  726.   STemp := snmPageList;
  727.   while (STemp <> nil) do begin
  728.     snmPageList := STemp^.snmpNext;
  729.     Dispose(STemp);
  730.     STemp := snmPageList;
  731.   end;
  732.   {destroy all the double node pages}
  733.   DTemp := dnmPageList;
  734.   while (DTemp <> nil) do begin
  735.     dnmPageList := DTemp^.dnmpNext;
  736.     Dispose(DTemp);
  737.     DTemp := dnmPageList;
  738.   end;
  739. end;
  740.  
  741. initialization
  742.   snmFreeList := nil;
  743.   snmPageList := nil;
  744.   dnmFreeList := nil;
  745.   dnmPageList := nil;
  746.  
  747. finalization
  748.   FinalizeUnit;
  749.  
  750. end.
  751.